package com.qs.controller;


import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.lang.UUID;
import cn.hutool.core.util.IdUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.qs.annotation.OperationLog;
import com.qs.constant.GoodsConstant;
import com.qs.constant.LoginConstant;
import com.qs.constant.RedisConstant;
import com.qs.constant.StatusConstant;
import com.qs.exception.ServiceException;
import com.qs.pojo.dto.UserDto;
import com.qs.pojo.entity.User;
import com.qs.pojo.vo.AdminVo;
import com.qs.pojo.vo.PasswordUserVo;
import com.qs.pojo.vo.PhoneUserVo;
import com.qs.response.Response;
import com.qs.response.ResponseEnum;
import com.qs.service.IAsyncService;
import com.qs.service.IOnlineService;
import com.qs.service.IUserService;
import com.qs.utils.EncryptUtils;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.bind.annotation.*;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * <p>
 * 管理员表 前端控制器
 * </p>
 *
 * @author author
 * @since 2023-11-11
 */
@Slf4j
@CrossOrigin
@RestController
@RequestMapping("/common")
public class LoginController {

    @Autowired
    private IUserService userService;

    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private IAsyncService asyncService;

    /**
     * 后台登录接口
     * @param adminVo
     * @return
     */
    @PostMapping("/login")
    public Response login(@RequestBody AdminVo adminVo) {
        QueryWrapper<User> wrapper = new QueryWrapper<>();
        wrapper.eq(!StringUtils.isEmpty(adminVo.getPhone()),"phone",adminVo.getPhone());
        User user = userService.getOne(wrapper);
        if(null == user) {
            throw new ServiceException(ResponseEnum.USER_NOT_EXITS);
        }
        if(!user.getName().equalsIgnoreCase(adminVo.getName())){
            throw new ServiceException(ResponseEnum.USERNAME_ERROR);
        }
        if(user.getRole().equalsIgnoreCase(LoginConstant.ROLE_USER)){
            throw new ServiceException(ResponseEnum.ILLEGAL_USER);
        }
        if(user.getStatus().getComment().equalsIgnoreCase(StatusConstant.STATUS_FORBID)){
            throw new ServiceException(ResponseEnum.USER_FORBID);
        }
        StpUtil.login(user.getId());
        UserDto userDto = new UserDto();
        BeanUtils.copyProperties(user,userDto);
        userDto.setKey(user.getId());
        Map<String,Object> map = new HashMap<>(2);
        map.put("user",userDto);
        map.put("authorization",StpUtil.getTokenValue());
        return Response.success(map);
    }

    /**
     * 前台密码登录接口
     * @param userVo
     * @return
     */
    @PostMapping("/passwordLogin")
    public Response passwordLogin(@RequestBody PasswordUserVo userVo) {
        QueryWrapper<User> wrapper = new QueryWrapper<>();
        wrapper.eq(!StringUtils.isEmpty(userVo.getNickName()),"nick_name",userVo.getNickName());
        User user = userService.getOne(wrapper);
        //判断用户是否存在
        if(null == user) {
            throw new ServiceException(ResponseEnum.USER_NOT_EXITS);
        }
        //判断用户密码是否正确
        if(StringUtils.isBlank(user.getPassword())){
            throw new ServiceException(ResponseEnum.PASSWORD_NULL);
        }
        String encryptPassword = EncryptUtils.MD5Password(userVo.getPassword());
        if(!user.getPassword().equalsIgnoreCase(encryptPassword)){
            throw new ServiceException(ResponseEnum.PASSWORD_ERROR);
        }
        //判断用户是否被禁用
        if(user.getStatus().getComment().equalsIgnoreCase(StatusConstant.STATUS_FORBID)){
            throw new ServiceException(ResponseEnum.USER_FORBID);
        }
        StpUtil.login(user.getId());
        UserDto userDto = new UserDto();
        BeanUtils.copyProperties(user,userDto);
        userDto.setKey(user.getId());
        //解密后的密码
        userDto.setPassword(encryptPassword);
        //需要设置一下key
        Map<String,Object> map = new HashMap<>(2);
        map.put("user",userDto);
        map.put("authorization",StpUtil.getTokenValue());
        return Response.success(map);
    }

    /**
     * 前台手机号登录接口
     * @param userVo
     * @return
     */
    @PostMapping("/phoneLogin")
    public Response phoneLogin(@RequestBody PhoneUserVo userVo) {
        //检验验证码是否过期
        String code = (String) redisTemplate.opsForValue().get(RedisConstant.MESSAGE_CODE + userVo.getPhone());
        if(StringUtils.isEmpty(code)){
            throw new ServiceException(ResponseEnum.CODE_TIMEOUT);
        }
        //对比验证码是否正确
        if(!userVo.getCode().equalsIgnoreCase(code)){
            throw new ServiceException(ResponseEnum.CODE_ERROR);
        }
        //判断用户是否存在
        QueryWrapper<User> wrapper = new QueryWrapper<>();
        wrapper.eq(!StringUtils.isEmpty(userVo.getPhone()),"phone",userVo.getPhone());
        User user = userService.getOne(wrapper);
        if(null == user) {
            throw new ServiceException(ResponseEnum.USER_NOT_EXITS);
        }
        //判断用户是否被禁用
        if(user.getStatus().getComment().equalsIgnoreCase(StatusConstant.STATUS_FORBID)){
            throw new ServiceException(ResponseEnum.USER_FORBID);
        }
        StpUtil.login(user.getId());
        UserDto userDto = new UserDto();
        BeanUtils.copyProperties(user,userDto);
        userDto.setKey(user.getId());
        //解密后的密码
        //需要设置一下key
        Map<String,Object> map = new HashMap<>(2);
        map.put("user",userDto);
        map.put("authorization",StpUtil.getTokenValue());
        return Response.success(map);
    }

    /**
     * 前台密码注册接口
     * @param userVo
     * @return
     */
    @PostMapping("/password/register")
    public Response passwordRegister(@RequestBody PasswordUserVo userVo) {
        //检测昵称是否重名
        QueryWrapper<User> wrapper = new QueryWrapper<>();
        wrapper.eq(!StringUtils.isEmpty(userVo.getNickName()),"nick_name",userVo.getNickName());
        User searchUser = userService.getOne(wrapper);
        if(null != searchUser) {
            if(StringUtils.isBlank(searchUser.getPassword())){
                //密码加密
                String encryptPassword = EncryptUtils.MD5Password(userVo.getPassword());
                searchUser.setPassword(encryptPassword);
                userService.updateById(searchUser);
            }else{
                throw new ServiceException(ResponseEnum.NICK_NAME_EXITS);
            }
        }else{
            //密码加密
            String encryptPassword = EncryptUtils.MD5Password(userVo.getPassword());
            userVo.setPassword(encryptPassword);
            User user = new User();
            BeanUtils.copyProperties(userVo,user);
            //将用户角色默认设置为普通用户
            user.setRole(LoginConstant.ROLE_USER);
            userService.save(user);
        }
        return Response.success();
    }


    /**
     * 前台手机号注册接口
     * @param userVo
     * @return
     */
    @PostMapping("/phone/register")
    public Response phoneRegister(@RequestBody PhoneUserVo userVo) {
        //检验验证码是否过期
        String code = (String) redisTemplate.opsForValue().get(RedisConstant.MESSAGE_CODE + userVo.getPhone());
        if(StringUtils.isEmpty(code)){
            throw new ServiceException(ResponseEnum.CODE_TIMEOUT);
        }
        //对比验证码是否正确
        if(!userVo.getCode().equalsIgnoreCase(code)){
            throw new ServiceException(ResponseEnum.CODE_ERROR);
        }
        //检测手机号是否存在
        QueryWrapper<User> wrapper = new QueryWrapper<>();
        wrapper.eq(!StringUtils.isEmpty(userVo.getPhone()),"phone",userVo.getPhone());
        User searchUser = userService.getOne(wrapper);
        if(null != searchUser) {
            throw new ServiceException(ResponseEnum.PHONE_EXITS);
        }
        User user = new User();
        BeanUtils.copyProperties(userVo,user);
        //将用户角色默认设置为普通用户
        user.setRole(LoginConstant.ROLE_USER);
        userService.save(user);
        return Response.success();
    }


    /**
     * 退出接口
     * @param
     * @return
     */
    @GetMapping("/logout/{key}")
    public Response logout(@PathVariable("key") Integer key) {
        log.info("退出登录：{}",key);
        asyncService.changeUserOfflineStatus(key);
        StpUtil.logout(key);
        return Response.success();
    }
}
